/**
 * https://open.feishu.cn/document/docs/bitable-v1/app-table-record/search#requestBody
 * 飞书API文档
 *
 *   const manager = await new FeishuTableManager('cli_a72e9c52c1bed00b', '6ESa55oPIPDYwwdkjYm1NbCXntfu2qoX').initialize('CMH1bVDv9aU7GZsuG8kcdrIAnnf')
    const d = await manager.queryRecords('TaskCrossTH')
 */

import http from '@/utils/http'
import { FeishuQueryResponse, FeishuResponse, FeishuTextItem, QueryFilterConditions, RecordFields, TableEnv, TableInfo } from './type'


export class FeishuTableManager {
  private appId: string
  private appSecret: string
  private baseUrl: string
  private token: string | null
  private tokenExpireTime: number | null
  private tableMap: Map<string, TableEnv> // 存储表名到环境参数的映射
  private currentAppToken: string | null // 当前使用的AppToken

  constructor(appId: string, appSecret: string) {
    this.appId = appId
    this.appSecret = appSecret
    this.baseUrl = 'https://open.feishu.cn/open-apis'
    this.token = null
    this.tokenExpireTime = null
    this.tableMap = new Map()
    this.currentAppToken = null
  }

  /**
   * 初始化方法 - 获取所有表格信息
   * @param appToken
   * @returns
   */
  async initialize(appToken: string) {
    if (!appToken) {
      throw new Error('appToken 参数是必需的')
    }

    try {
      this.currentAppToken = appToken
      await this.ensureValidToken()
      await this.loadAllTables(appToken)
      console.log('飞书表格管理器初始化完成，共加载表格数量:', this.tableMap.size)

      return this
    } catch (error) {
      console.error('飞书表格管理器初始化失败:', error)
      throw error
    }
  }

  /**
   * 获取当前AppToken
   * @returns string
   */
  getCurrentAppToken(): string {
    if (!this.currentAppToken) {
      throw new Error('请先调用 initialize 方法初始化')
    }
    return this.currentAppToken
  }

  /**
   * 获取所有表格信息
   * @param appToken
   */
  private async loadAllTables(appToken: string): Promise<void> {
    const requestFn = async () => {
      const url = `${this.baseUrl}/bitable/v1/apps/${appToken}/tables`
      const result = await http.get(url, {
        headers: {
          'Authorization': `Bearer ${this.token}`,
        }
      })

      if (result.code !== 0) {
        console.error('获取表格列表失败:', result)
        throw new Error(result.msg || '获取表格列表失败')
      }

      // 处理表格数据
      const tables: TableInfo[] = result.data.items || []
      tables.forEach((table: TableInfo) => {
        const tableEnv: TableEnv = {
          baseToken: appToken,
          tableId: table.table_id
        }
        this.tableMap.set(table.name, tableEnv)
      })

      return result
    }

    await this.requestWithTokenRetry(requestFn)
  }

  /**
   * 手动添加表格信息（用于单个表格初始化）
   * @param tableName 表格Name
   * @param tableId   表格ID
   */
  async addTableInfo(tableName: string, tableId: string): Promise<void> {
    const appToken = this.getCurrentAppToken()
    const tableEnv: TableEnv = {
      baseToken: appToken,
      tableId: tableId
    }
    this.tableMap.set(tableName, tableEnv)
  }

  /**
   * 根据表名获取表格环境参数
   * @param tableName  表名
   * @returns
   */
  getTableEnvs(tableName: string): TableEnv {
    const tableEnv = this.tableMap.get(tableName)
    if (!tableEnv) {
      throw new Error(`未找到表名为"${tableName}"的表格信息，请检查表名是否正确或先初始化表格信息`)
    }
    return { ...tableEnv } // 返回副本以避免外部修改
  }

  /**
   * 获取所有表格名称列表
   * @returns
   */
  getTableNames(): string[] {
    return Array.from(this.tableMap.keys())
  }

  /**
   * 检查表格是否存在
   * @param tableName
   * @returns
   */
  hasTable(tableName: string): boolean {
    return this.tableMap.has(tableName)
  }

  /**
   * 重新加载所有表格信息
   */
  async reloadTables(): Promise<void> {
    const appToken = this.getCurrentAppToken()
    this.tableMap.clear()
    await this.loadAllTables(appToken)
    console.log('表格信息重新加载完成，当前表格数量:', this.tableMap.size)
  }

  /**
   * 获取访问令牌
   * @returns
   */
  async getAccessToken(): Promise<string> {
    try {
      const response = await http.post(`${this.baseUrl}/auth/v3/tenant_access_token/internal`, {
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          app_id: this.appId,
          app_secret: this.appSecret
        })
      })

      if (response.code !== 0) {
        throw new Error(response.msg || '获取token失败')
      }

      this.token = response.tenant_access_token
      // 设置token过期时间（飞书token通常有效期为2小时，这里设置为1小时55分钟以确保安全）
      this.tokenExpireTime = Date.now() + (115 * 60 * 1000)

      return this.token
    } catch (error) {
      console.error('获取飞书访问令牌失败:', error)
      throw error
    }
  }

  // 检查token是否过期
  private isTokenExpired(): boolean {
    if (!this.token || !this.tokenExpireTime) {
      return true
    }
    return Date.now() >= this.tokenExpireTime
  }

  // 确保token有效
  private async ensureValidToken(): Promise<void> {
    if (this.isTokenExpired()) {
      await this.getAccessToken()
    }
  }

  // 带token过期重试的请求方法
  private async requestWithTokenRetry(
    requestFn: () => Promise<any>,
    maxRetries: number = 1
  ): Promise<any> {
    let lastError: any

    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        await this.ensureValidToken()
        const result = await requestFn()

        // 检查是否是token过期错误
        if (result.code === 99991663 || result.code === 99991664) {
          // token过期，清除token并重试
          this.token = null
          this.tokenExpireTime = null
          if (attempt < maxRetries) {
            console.log(`Token已过期，正在重试... (${attempt + 1}/${maxRetries})`)
            continue
          }
        }

        return result
      } catch (error: any) {
        lastError = error

        // 检查错误信息中是否包含token过期相关的内容
        if (error.message?.includes('token') ||
          error.message?.includes('expired') ||
          error.message?.includes('认证') ||
          error.message?.includes('auth')) {
          this.token = null
          this.tokenExpireTime = null
          if (attempt < maxRetries) {
            console.log(`Token可能已过期，正在重试... (${attempt + 1}/${maxRetries})`)
            continue
          }
        }

        // 其他错误直接抛出
        throw error
      }
    }

    throw lastError
  }

  // 读取表格数据 - 现在只需要表名
  async readRecords(tableName: string): Promise<FeishuResponse> {
    const tableEnv = this.getTableEnvs(tableName)
    const requestFn = async () => {
      const url = `${this.baseUrl}/bitable/v1/apps/${tableEnv.baseToken}/tables/${tableEnv.tableId}/records/search`
      return await http.get(url, {
        headers: {
          'Authorization': `Bearer ${this.token}`,
        }
      })
    }

    return await this.requestWithTokenRetry(requestFn)
  }

  // 复杂查询 - 现在只需要表名
  async queryRecords<T = FeishuTextItem[]>(
    tableName: string,
    filterConditions: QueryFilterConditions = {},
    pageSize: number = 100,
    pageToken: string | null = null
  ): Promise<FeishuResponse<FeishuQueryResponse<T>>> {
    const tableEnv = this.getTableEnvs(tableName)
    const requestFn = async () => {
      const url = `${this.baseUrl}/bitable/v1/apps/${tableEnv.baseToken}/tables/${tableEnv.tableId}/records/search`

      // 添加分页参数
      if (pageSize) {
        filterConditions.page_size = pageSize
      }
      if (pageToken) {
        filterConditions.page_token = pageToken
      }

      const result = await http.post(url, {
        headers: {
          'Authorization': `Bearer ${this.token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(filterConditions)
      })

      if (result.code !== 0) {
        console.error('飞书API错误:', result)
        throw new Error(result.msg || '飞书API调用失败')
      }

      return result
    }

    return await this.requestWithTokenRetry(requestFn)
  }

  // 添加行数据 - 现在只需要表名
  async addRecord(tableName: string, fields: RecordFields): Promise<FeishuResponse> {
    const tableEnv = this.getTableEnvs(tableName)
    const requestFn = async () => {
      const url = `${this.baseUrl}/bitable/v1/apps/${tableEnv.baseToken}/tables/${tableEnv.tableId}/records`
      const result = await http.post(url, {
        headers: {
          'Authorization': `Bearer ${this.token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          fields: fields
        })
      })
      return result
    }

    return await this.requestWithTokenRetry(requestFn)
  }

  // 更新单元格 - 现在只需要表名和记录ID
  async updateRecord(tableName: string, recordId: string, fields: RecordFields): Promise<FeishuResponse> {
    const tableEnv = this.getTableEnvs(tableName)
    const requestFn = async () => {
      const url = `${this.baseUrl}/bitable/v1/apps/${tableEnv.baseToken}/tables/${tableEnv.tableId}/records/${recordId}`
      const result = await http.put(url, {
        headers: {
          'Authorization': `Bearer ${this.token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          fields: fields
        })
      })
      return result
    }

    return await this.requestWithTokenRetry(requestFn)
  }

  // 批量更新记录 - 现在只需要表名
  async batchUpdateRecords(
    tableName: string,
    records: { record_id: string; fields: RecordFields }[]
  ): Promise<FeishuResponse> {
    const tableEnv = this.getTableEnvs(tableName)
    const requestFn = async () => {
      const url = `${this.baseUrl}/bitable/v1/apps/${tableEnv.baseToken}/tables/${tableEnv.tableId}/records/batch_update`

      const result = await http.post(url, {
        headers: {
          'Authorization': `Bearer ${this.token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          records: records
        })
      })

      if (result.code !== 0) {
        console.error('飞书批量更新API错误:', result)
        throw new Error(result.msg || '飞书批量更新API调用失败')
      }

      return result
    }

    return await this.requestWithTokenRetry(requestFn)
  }

  // 删除行 - 现在只需要表名和记录ID
  async deleteRecord(tableName: string, recordId: string): Promise<FeishuResponse> {
    const tableEnv = this.getTableEnvs(tableName)
    const requestFn = async () => {
      const url = `${this.baseUrl}/bitable/v1/apps/${tableEnv.baseToken}/tables/${tableEnv.tableId}/records/${recordId}`
      const result = await http.delete(url, {
        headers: {
          'Authorization': `Bearer ${this.token}`,
          'Content-Type': 'application/json'
        }
      })
      return result
    }

    return await this.requestWithTokenRetry(requestFn)
  }

  // 手动清除token（用于强制刷新）
  clearToken(): void {
    this.token = null
    this.tokenExpireTime = null
  }

  // 获取token状态
  getTokenStatus(): { hasToken: boolean; isExpired: boolean } {
    return {
      hasToken: !!this.token,
      isExpired: this.isTokenExpired()
    }
  }

  // 获取管理器状态
  getManagerStatus(): {
    hasToken: boolean
    isTokenExpired: boolean
    tableCount: number
    currentAppToken: string | null
    tableNames: string[]
  } {
    return {
      hasToken: !!this.token,
      isTokenExpired: this.isTokenExpired(),
      tableCount: this.tableMap.size,
      currentAppToken: this.currentAppToken,
      tableNames: this.getTableNames()
    }
  }
}